#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e5 + 10;

int n, ans = N;
int h[N], e[N * 2], ne[N * 2], idx;
bool st[N];
 
void add(int a, int b) { // 邻接表存稀疏图，添加一条由a指向b的边 
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

int dfs(int u) { // dfs(u) 的作用为搜索以u为父结点的子树的子节点个数 
	int res = 0, sum = 0; 
	    // res 记录最大联通快的节点数，sum 记录以u为父结点的子树的子节点个数（不含该根结点） 
	st[u] = true; // 标记该点已被搜索过 
	
	for (int i = h[u]; i != -1; i = ne[i]) { // 遍历以u为父结点的子树 
		int j = e[i]; // 取每个点的值来做下标判断是否被搜索过 
		if (!st[j]) { // 如果没被搜索过 
			int s = dfs(j); // 继续遍历以该点为父结点的子树的子节点个数 
			res = max(res, s); // 更新子节点的最大值 
			sum += s; // 加入到父节点所属的树中的子节点个数（递归处理） 
		}
	}
	
	res = max(res, n - sum - 1); 
	    // 取联通块节点数的最大值（即将该树的总节点数和除此之外的所有剩余的子节点比较） 
	ans = min(res, ans); // 取最大联通块的最小值 
	
	return sum + 1; // 返回该树的子节点个数 
}

int main() {
	cin >> n; // 输入总结点个数 
	
	memset(h, -1, sizeof h); // 初始化表头 
	
	for (int i = 0; i < n - 1; ++ i) { // 添加 n - 1 条边 
		int a, b;
		scanf("%d%d", &a, &b);
		add(a, b), add(b, a); // 无向图 
	}
	
	dfs(1); // 开始搜索，随便选一个 u < n 的点即可 
	
	cout << ans << endl; // 输出答案 
	
	return 0; // 结束快乐 
}